package com.javacodegeeks.enterprise.rest.jersey;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URLEncoder;

import javafx.application.HostServices;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpSession;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import oauth.signpost.OAuthConsumer;
import oauth.signpost.OAuthProvider;
import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;
import oauth.signpost.commonshttp.CommonsHttpOAuthProvider;

import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CookieStore;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.HttpContext;
import org.apache.http.HttpResponse;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;

import java.util.HashMap;
import java.util.Map;

import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONArray;

@SuppressWarnings("deprecation")
@Path("/dropboxAPI")
public class DropboxAPI extends HttpServlet implements IClouding{

	private String ACCESS_TOKEN_KEY = "";
	private String ACCESS_TOKEN_SECRET = "";

	private String httpResponse;
	private static DefaultHttpClient  httpclient;

	HttpURLConnection con;
	HostServices hostServices;

	CookieStore cookieStore;
	HttpContext httpContext;
	HttpSession session;
	HttpGet httpget;
	HttpResponse response;
	private static HashMap<String, String> listFolder;
	private static final String CONSUMER_KEY = "9j8ijhrsht8rmu1";
	private static final String CONSUMER_SECRET = "4lsrajr94b88yjt";

	private static final String REQUEST_URL = "https://api.dropbox.com/1/oauth/request_token";
	private static final String AUTHORIZE_URL = "https://www.dropbox.com/1/oauth/authorize";
	private static final String ACCESS_URL = "https://api.dropbox.com/1/oauth/access_token";

	private static final String CALLBACK_URL = "http://localhost:8080/FileExplorer.html";
	private static OAuthProvider provider;
	private static OAuthConsumer consumer;

	private static String folderResult;
	private static JSONObject directoryJSON;

	
	@GET
	@Path("/requestOauth")
	public Response initialRequest() throws Exception{
		httpclient = new DefaultHttpClient();
		folderResult = "";

		this.consumer = new CommonsHttpOAuthConsumer(CONSUMER_KEY,
				CONSUMER_SECRET);		
		this.provider = new CommonsHttpOAuthProvider(REQUEST_URL, ACCESS_URL,
				AUTHORIZE_URL);
		
		String url = provider.retrieveRequestToken(consumer, CALLBACK_URL);
		return Response.status(200).entity(url).build();
	}
	
	
	@GET
	@Path("/requestAccess/{verifyCode}")
	@Produces(MediaType.APPLICATION_JSON)
	public Response getVerify(@PathParam("verifyCode") String verifyCode) throws Exception {		
		System.out.println(">>> Verify code: " + verifyCode);	
		
		provider.retrieveAccessToken(consumer, verifyCode);

		ACCESS_TOKEN_KEY = consumer.getToken();
		ACCESS_TOKEN_SECRET = consumer.getTokenSecret();

		consumer.setTokenWithSecret(ACCESS_TOKEN_KEY, ACCESS_TOKEN_SECRET);

		System.out.println(">>> Access token secret: "
				+ ACCESS_TOKEN_SECRET + "\n Access token key: " + ACCESS_TOKEN_KEY);
		
		String outputGetFolder = getMetadata("");
		return Response.status(200).entity(outputGetFolder).build();
	}
	

	/*
	 * Get user account info
	 */
	private void getAccountInfo() {
		System.out.println("\nCalling /account/info...");
		String urlAcc = "https://api.dropbox.com/1/account/info";
		httpResponse = makeHttpGetRequest(urlAcc,
				makeHeaderWithToken(ACCESS_TOKEN_KEY, ACCESS_TOKEN_SECRET));
		System.out.println(httpResponse);
	}

	/*
	 * Move and rename file In rename file case, the fromPath and toPath should
	 * have the same parent folder Ex: A1/oldname.txt ==> A1/newname.txt
	 */
	private void moveAndRenameFile1(String fromPath, String toPath) {
		System.out.println("\nMove file from " + fromPath + " to " + toPath);
		String requestURL = String
				.format("https://api.dropbox.com/1/fileops/move?root=dropbox&from_path=%s&to_path=%s",
						URLEncoder.encode(fromPath), URLEncoder.encode(toPath));
		System.out.println(requestURL);
		httpResponse = makeHttpGetRequest(requestURL,
				makeHeaderWithToken(ACCESS_TOKEN_KEY, ACCESS_TOKEN_SECRET));
	}

	// @POST
	// @Path("/image-upload")
	// @Consumes("multipart/form-data")
	public void UploadFile1(String destPath, String filePath) throws Exception {
		System.out.println("\nUpload file...");
		consumer.setTokenWithSecret(ACCESS_TOKEN_KEY, ACCESS_TOKEN_SECRET);

		try {
			System.out.println(filePath);

			File file = new File(filePath);
			if (file.exists()) {
				// get absolute path
				String absPath = file.getAbsolutePath();
				// prints
				System.out.println("Absolute Pathname " + absPath
						+ "\nfile name = " + file.getName());
			}

			String requestURL = String.format(
					"https://api-content.dropbox.com/1/files_put/dropbox/%s",
					destPath + "/" + file.getName());

			System.out.println(requestURL);
			HttpPost postRequest = new HttpPost(requestURL);

			// Set various attributes
			// postRequest.addHeader("Authorization",
			// makeHeaderWithToken(OAUTH_TOKEN_KEY, OAUTH_TOKEN_SECRET));
			postRequest.addHeader("Content-Type", "application/octect-stream");

			MultipartEntity multiPartEntity = new MultipartEntity();
			FileBody fileBody = new FileBody(file);

			// Prepare payload
			multiPartEntity.addPart("attachment", fileBody);

			// Set to request body
			postRequest.setEntity(multiPartEntity);

			consumer.sign(postRequest);

			// Send request
			HttpResponse response = httpclient.execute(postRequest);

			// Verify response if any
			if (response != null) {
				System.out.println(response.getStatusLine().getStatusCode());
			}

			BufferedReader rd = new BufferedReader(new InputStreamReader(
					response.getEntity().getContent()));

			StringBuffer result = new StringBuffer();
			String line = "";
			while ((line = rd.readLine()) != null) {
				result.append(line);
			}
			System.out.println(result.toString());

		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}


	private String makeHeaderWithToken(String key, String secret) {
		String header = "OAuth oauth_version=\"1.0\", oauth_signature_method=\"PLAINTEXT\"";
		header += ", oauth_consumer_key=\"" + CONSUMER_KEY + "\"";
		header += ", oauth_token=\"" + key + "\"";
		header += ", oauth_signature=\"" + CONSUMER_SECRET + "&" + secret
				+ "\"";
		return header;
	}

	@SuppressWarnings("null")
	private String getMetadata(String path) {
		listFolder = new HashMap<String, String>();
		getAllListFolderFile(path);
		for (Map.Entry<String, String> entry : listFolder.entrySet()) {
			System.out.println("\nKey = " + entry.getKey() + ", Value = "
					+ entry.getValue());
		}
		return jsonAnalysis();
	}

	private String jsonAnalysis() {
		JSONObject entryObj;
		JSONArray contentJA;
		JSONArray contentsJA = new JSONArray();
		String init = folderResult.substring(0,
				folderResult.indexOf("contents") - 3)
				+ "}";
		System.out.println("\n<<< Init JSON: " + init);
		try {
			directoryJSON = new JSONObject(init);
		} catch (JSONException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

		try {
			JSONObject jsonObj = new JSONObject(folderResult);
			JSONArray contentsArr = jsonObj.getJSONArray("contents");
			System.out.println("<<< Exist directory: ");
			for (int i = 0; i < contentsArr.length(); i++) {
				System.out.println((contentsArr.getJSONObject(i).get("path")
						.toString()));
			}

			for (Map.Entry<String, String> entry : listFolder.entrySet()) {
				// String entryDicrectory = entry.getKey().substring(0,
				// entry.getKey().lastIndexOf("/"));
				String entryDicrectory = entry.getKey();
				System.out.println("\n<<< Entry directory: " + entryDicrectory);

				for (int i = 0; i < contentsArr.length(); i++) {
					String existConDicrectory = (contentsArr.getJSONObject(i)
							.get("path").toString());
					System.out.println("<<< existConDicrectory: "
							+ existConDicrectory);

					if (existConDicrectory.equals(entryDicrectory)) {
						break;
					} else {
						String subPath = entry.getKey().substring(0,
								entry.getKey().lastIndexOf("/"));
						System.out.println("<<< Sub path: " + subPath);
						if (existConDicrectory.compareTo(subPath) == 0) {
							System.out.println("\n<<< getJSONObject: \n"
									+ contentsArr.getJSONObject(i));

							contentJA = new JSONArray();
							entryObj = new JSONObject(entry.getValue());
							contentJA.put(entryObj);
							
							contentsArr.getJSONObject(i).put(
									"contents", contentJA);
							
							contentsJA.put(contentsArr.getJSONObject(i));
							
							System.out.print(contentsArr.getJSONObject(i));
							break;
						}
					}
				}
			}
				

			directoryJSON.put("contents", contentsJA);
			System.out.println("\n<<< JSON Directory: \n"
					+ directoryJSON);
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return directoryJSON.toString();
	}

	private HashMap<String, String> getAllListFolderFile(String path) {
		String subPath = "";
		
		try {
			httpget = new HttpGet("https://api.dropbox.com/1/metadata/dropbox/"
					+ path);
			httpget.addHeader("Authorization",
					makeHeaderWithToken(ACCESS_TOKEN_KEY, ACCESS_TOKEN_SECRET));

			response = httpclient.execute(httpget);
			BufferedReader rd = new BufferedReader(new InputStreamReader(
					response.getEntity().getContent()));

			String line = "";
			StringBuilder content = new StringBuilder();
			while ((line = rd.readLine()) != null) {
				content.append(line);
			}

			System.out.println("<<< Get file at path = " + path);
			System.out.println("<<< " + content.toString());

			JSONObject jsonObj = new JSONObject(content.toString());
			JSONArray contentsArr = jsonObj.getJSONArray("contents");
			
			if (folderResult == "") {
				folderResult = content.toString();
			}
			for (int i = 0; i < contentsArr.length(); i++) {
				System.out.println("\nIndex = " + i);
				System.out.println(contentsArr.getJSONObject(i));

				subPath = (contentsArr.getJSONObject(i)).get("path").toString();
				
				listFolder
						.put(subPath, contentsArr.getJSONObject(i).toString());

				if ((Boolean) (contentsArr.getJSONObject(i)).get("is_dir")) {
					getAllListFolderFile(subPath.substring(1));
				}
			}
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return listFolder;
	}

	private String makeHttpGetRequest(String urlStr, String authHeader) {
		// consumer.setTokenWithSecret(ACCESS_TOKEN_KEY, ACCESS_TOKEN_SECRET);
		StringBuffer result = null;

		httpget = new HttpGet(urlStr);
		httpget.addHeader("Authorization", authHeader);

		try {
			// consumer.sign(httpget);
			response = httpclient.execute(httpget, httpContext);
			System.out.println("Response Code : "
					+ response.getStatusLine().getStatusCode());
			BufferedReader rd = new BufferedReader(new InputStreamReader(
					response.getEntity().getContent()));

			result = new StringBuffer();
			String line = "";
			while ((line = rd.readLine()) != null) {
				result.append(line);
			}
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result.toString();
	}


	


	public void getFile(String path) {
		// TODO Auto-generated method stub
		
	}


	public void moveAndRenameFile(String fromPath, String toPath) {
		// TODO Auto-generated method stub
		
	}


	public void getListFile(String pathname) {
		// TODO Auto-generated method stub
		
	}


	public void getsizeFile(String path) {
		// TODO Auto-generated method stub
		
	}


	public void UploadFile(String destPath, String filePath) {
		// TODO Auto-generated method stub
		
	}


	
}
